/**
 * This file is part of aion-unique <aion-unique.smfnew.com>.
 *
 * aion-unique is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * aion-unique is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * aion-unique. If not, see <http://www.gnu.org/licenses/>.
 */
package com.aionengine.gameserver.network.aion.serverpackets;

import com.aionengine.gameserver.controllers.attack.AttackResult;
import com.aionengine.gameserver.model.gameobjects.Creature;
import com.aionengine.gameserver.model.gameobjects.player.Player;
import com.aionengine.gameserver.network.aion.AionConnection;
import com.aionengine.gameserver.network.aion.AionServerPacket;

import java.util.List;

/**
 * @author -Nemesiss-, Sweetkr
 */
public class SM_ATTACK extends AionServerPacket {

    private int attackno;
    private int time;
    private int type;
    private List<AttackResult> attackList;
    private Creature attacker;
    private Creature target;

    public SM_ATTACK(Creature attacker, Creature target, int attackno, int time, int type, List<AttackResult> attackList) {
        this.attacker = attacker;
        this.target = target;
        this.attackno = attackno;// empty
        this.time = time;// empty
        this.type = type;// empty
        this.attackList = attackList;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void writeImpl(AionConnection con) {
        writeD(attacker.getObjectId());
        writeC(attackno); // unknown
        writeH(time); // unknown
        writeC(0);
        writeC(type); // 0, 1, 2
        writeD(target.getObjectId());

        int attackerMaxHp = attacker.getLifeStats().getMaxHp();
        int attackerCurrHp = attacker.getLifeStats().getCurrentHp();
        int targetMaxHp = target.getLifeStats().getMaxHp();
        int targetCurrHp = target.getLifeStats().getCurrentHp();

        writeC((int) (100f * targetCurrHp / targetMaxHp)); // target %hp
        writeC((int) (100f * attackerCurrHp / attackerMaxHp)); // attacker %hp

        // TODO refactor attack controller
        switch (attackList.get(0).getAttackStatus().getId()) // Counter skills
        {
            case -60: // case CRITICAL_BLOCK
            case 4: // case BLOCK
                writeH(32);
                break;
            case -62: // case CRITICAL_PARRY
            case 2: // case PARRY
                writeH(64);
                break;
            case -64: // case CRITICAL_DODGE
            case 0: // case DODGE
                writeH(128);
                break;
            case -58: // case PHYSICAL_CRITICAL_RESIST
            case 6: // case RESIST
                writeH(256); // need more info becuz sometimes 0
                break;
            default:
                writeH(0);
                break;
        }
        //setting counter skill from packet to have the best synchronization of time with client
        if (target instanceof Player) {
            if (attackList.get(0).getAttackStatus().isCounterSkill())
                ((Player) target).setLastCounterSkill(attackList.get(0).getAttackStatus());
        }

        writeH(0);

        //TODO! those 2h (== d) up is some kind of very weird flag...
        //writeD(attackFlag);
        /*if(attackFlag & 0x10A0F != 0)
		{
			writeF(0);
			writeF(0);
			writeF(0);
		}
		if(attackFlag & 0x10010 != 0)
		{
			writeC(0);
		}
		if(attackFlag & 0x10000 != 0)
		{
			writeD(0);
			writeD(0);
		}*/

        writeC(attackList.size());
        for (AttackResult attack : attackList) {
            writeD(attack.getDamage());
            writeC(attack.getAttackStatus().getId());

            byte shieldType = (byte) attack.getShieldType();
            writeC(shieldType);

            /**
             * shield Type:
             * 1: reflector
             * 2: normal shield
             * 8: protect effect (ex. skillId: 417 Bodyguard)
             * TODO find out 4
             */
            switch (shieldType) {
                case 0:
                case 2:
                    break;
                case 8:
                case 10:
                    writeD(attack.getProtectorId()); // protectorId
                    writeD(attack.getProtectedDamage()); // protected damage
                    writeD(attack.getProtectedSkillId()); // skillId
                    break;
                default:
                    writeD(attack.getProtectorId()); // protectorId
                    writeD(attack.getProtectedDamage()); // protected damage
                    writeD(attack.getProtectedSkillId()); // skillId
                    writeD(attack.getReflectedDamage()); // reflect damage
                    writeD(attack.getReflectedSkillId()); // skill id
                    break;
            }
        }
        writeC(0);
    }

}